package com.sh.dc.controller;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sh.dc.common.BaseResult;
import com.sh.dc.common.enums.BizCodeEnum;
import com.sh.dc.common.enums.TaskLogAddTypeEnum;
import com.sh.dc.common.enums.TaskStatusEnum;
import com.sh.dc.common.pojo.bo.TaskLogSaveBO;
import com.sh.dc.common.pojo.bo.TaskSolverSaveBO;
import com.sh.dc.common.pojo.bo.TaskSolverStatusUpdateBO;
import com.sh.dc.common.pojo.query.TaskSolverPageQuery;
import com.sh.dc.entity.FileResource;
import com.sh.dc.entity.Solver;
import com.sh.dc.entity.TaskLog;
import com.sh.dc.entity.TaskSolver;
import com.sh.dc.service.ISolverService;
import com.sh.dc.service.ITaskLogService;
import com.sh.dc.service.ITaskSolverService;
import io.micrometer.common.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.Optional;

/**
 * <p>
 * 求解任务表 前端控制器
 * </p>
 *
 * @author zhenlan
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/taskSolver")
public class TaskSolverController {

    @Autowired
    private ITaskSolverService taskSolverService;

    @Autowired
    private ITaskLogService taskLogService;

    @Autowired
    private ISolverService solverService;

    @PostMapping("/save")
    public BaseResult save(@RequestBody TaskSolverSaveBO taskSolverSaveBO) {
        TaskSolver taskSolver = new TaskSolver();
        BeanUtil.copyProperties(taskSolverSaveBO, taskSolver);
        taskSolver.setUpdateTime(new Date());
        if (taskSolver.getSolverId() != null && StringUtils.isBlank(taskSolver.getSolverName())) {
            Optional<Solver> opt = solverService.getOptById(taskSolver.getSolverId());
            if (!opt.isPresent()) {
                return BaseResult.fail(BizCodeEnum.SOLVER_NOT_EXISTED);
            }
            taskSolver.setSolverName(opt.get().getName());
        }
        taskSolverService.saveOrUpdate(taskSolver);
        return BaseResult.success(taskSolver.getId());
    }

    @PostMapping("/page")
    public BaseResult page(@RequestBody TaskSolverPageQuery query) {
        return BaseResult.success(taskSolverService.getTaskSolverPage(query));
    }

    @PostMapping("/status")
    public BaseResult statusCB(@RequestBody TaskSolverStatusUpdateBO bo) {
        Optional<TaskSolver> optById = taskSolverService.getOptById(bo.getTaskId());
        if (!optById.isPresent()) {
            return BaseResult.fail(BizCodeEnum.TASK_NOT_EXISTED);
        }
        TaskSolver taskSolver = optById.get();
        Date now = new Date();
        if (TaskStatusEnum.RUNNING.getCode().equals(bo.getStatus())) {
            taskSolver.setStartTime(bo.getTime() == null ? now : bo.getTime());
        } else if (TaskStatusEnum.SUCCESS.getCode().equals(bo.getStatus())
                || TaskStatusEnum.FAILED.getCode().equals(bo.getStatus())
                || TaskStatusEnum.TERMINATED.getCode().equals(bo.getStatus())) {
            taskSolver.setEndTime(bo.getTime() == null ? now : bo.getTime());
        }
        taskSolver.setStatus(bo.getStatus());
        taskSolver.setUpdateTime(new Date());
        taskSolverService.updateById(taskSolver);
        return BaseResult.success(taskSolver);
    }

    @PostMapping("/log")
    public BaseResult saveTaskLog(@RequestBody TaskLogSaveBO bo) {
        QueryWrapper<TaskLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("task_id", bo.getTaskId());
        TaskLog taskLog = new TaskLog();
        TaskLog taskLogDB  = taskLogService.getOne(queryWrapper);
        if (taskLogDB != null) {
            taskLog.setId(taskLogDB.getId());
        }
        if (taskLogDB != null && TaskLogAddTypeEnum.APPEND.getCode().equals(bo.getType())) {
            taskLog.setLogMsg(taskLogDB.getLogMsg() + bo.getLogMsg());
        } else {
            taskLog.setLogMsg(bo.getLogMsg());
        }
        taskLog.setTaskId(bo.getTaskId());
        taskLogService.saveOrUpdate(taskLog);
        return BaseResult.success();
    }

    @GetMapping("/countStatus")
    public BaseResult countTaskStatus() {
        return BaseResult.success(taskSolverService.countStatus());
    }

    @GetMapping("/{id}")
    public BaseResult getById(@PathVariable("id") Integer id) {
        Optional<TaskSolver> opt = taskSolverService.getOptById(id);
        if (opt.isPresent()) {
            return BaseResult.success(taskSolverService.transferToDto(opt.get()));
        }
        return BaseResult.fail(BizCodeEnum.TASK_NOT_EXISTED);
    }

    @GetMapping("/log/{taskId}")
    public BaseResult getLogById(@PathVariable("taskId") Integer taskId) {
        Optional<TaskSolver> opt = taskSolverService.getOptById(taskId);
        if (!opt.isPresent()) {
            return BaseResult.fail(BizCodeEnum.TASK_NOT_EXISTED);
        }
        QueryWrapper<TaskLog> wrapper = new QueryWrapper<>();
        wrapper.eq("task_id", taskId);
        return BaseResult.success(taskLogService.getOne(wrapper));
    }

    @PostMapping("/stop/{taskId}")
    public BaseResult stopTask(@PathVariable("taskId") Integer taskId) {
        Optional<TaskSolver> opt = taskSolverService.getOptById(taskId);
        if (!opt.isPresent()) {
            return BaseResult.fail(BizCodeEnum.TASK_NOT_EXISTED);
        }
        try {
            taskSolverService.stopTask(taskId);
            TaskSolver taskSolver = opt.get();
            taskSolver.setStatus(TaskStatusEnum.TERMINATED.getCode());
            taskSolver.setEndTime(new Date());
            taskSolverService.saveOrUpdate(taskSolver);
            return BaseResult.success();
        } catch (Exception e) {
            return BaseResult.fail("停止任务失败");
        }
    }

}
